﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace IRC.IRepairClouds.DataLayer
{
    public class PostprocessEnumerable<T> : IEnumerable<T>
    {
        public class Enumerator : IEnumerator<T>
        {
            private IEnumerator<T> _enumerator;
            private Action<T> _shaper;

            public Enumerator(IEnumerator<T> enumerator, Action<T> shaper)
            {
                _enumerator = enumerator;
                _shaper = shaper;
            }

            #region IEnumerator<T> Members

            public T Current
            {
                get
                {
                    var item = _enumerator.Current;
                    _shaper(item);
                    return item;
                }
            }

            #endregion

            #region IDisposable Members

            public void Dispose()
            {
                _enumerator.Dispose();
            }

            #endregion

            #region IEnumerator Members

            object System.Collections.IEnumerator.Current
            {
                get
                {
                    var item = _enumerator.Current;
                    if (_shaper != null)
                        _shaper(item);
                    return item;
                }
            }

            public bool MoveNext()
            {
                return _enumerator.MoveNext();
            }

            public void Reset()
            {
                _enumerator.Reset();
            }

            #endregion
        }

        private IEnumerable<T> _query;
        private Action<T> _shaper;

        public PostprocessEnumerable(IEnumerable<T> query, Action<T> shaper)
        {
            if (query == null)
                throw new ArgumentNullException("query");
            _query = query;
            _shaper = shaper;
        }

        #region IEnumerable<T> Members

        public IEnumerator<T> GetEnumerator()
        {
            return new Enumerator(_query.GetEnumerator(), _shaper);
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return new Enumerator(_query.GetEnumerator(), _shaper);
        }

        #endregion
    }




    public class PostprocessEnumerable<T, TRes> : IEnumerable<TRes>
    {
        public class Enumerator : IEnumerator<TRes>
        {
            private IEnumerator<T> _enumerator;
            private Func<T, TRes> _shaper;

            public Enumerator(IEnumerator<T> enumerator, Func<T, TRes> shaper)
            {
                _enumerator = enumerator;
                _shaper = shaper;
            }

            #region IEnumerator<T> Members

            public TRes Current
            {
                get
                {
                    var item = _enumerator.Current;
                    return _shaper(item);
                }
            }

            #endregion

            #region IDisposable Members

            public void Dispose()
            {
                _enumerator.Dispose();
            }

            #endregion

            #region IEnumerator Members

            object System.Collections.IEnumerator.Current
            {
                get
                {
                    var item = _enumerator.Current;
                    if (item != null)
                        _shaper(item);
                    return null;
                }
            }

            public bool MoveNext()
            {
                return _enumerator.MoveNext();
            }

            public void Reset()
            {
                _enumerator.Reset();
            }

            #endregion
        }

        private IEnumerable<T> _query;
        private Func<T, TRes> _shaper;

        public PostprocessEnumerable(IEnumerable<T> query, Func<T, TRes> shaper)
        {
            if (query == null)
                throw new ArgumentNullException("query");
            _query = query;
            _shaper = shaper;
        }

        #region IEnumerable<T> Members

        public IEnumerator<TRes> GetEnumerator()
        {
            return new Enumerator(_query.GetEnumerator(), _shaper);
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return new Enumerator(_query.GetEnumerator(), _shaper);
        }

        #endregion
    }
}
